import json
import math
import os
from collections import namedtuple

import stackprinter

from devices.mengy_ks833 import KS833_OutputStatus

DISCT_RO = (
    (0x0000, 92),  # 实时更新信息类
    (0x0900, 4),  # 事件信息状态寄存器
    (0x0920, 10),  # 最新保护事件寄存器
    (0x0950, 23),  # 历史保护事件寄存器
    (0x0A00, 8),  # 历史遥信事件寄存器
    (0x0E00, 8),  # 装置调试信息寄存器
)

DISCT_RW = (
    # (0x0000, 8),  # 实时更新信息类 时间 远方就地状态
    # (0x0040, 4),  # 实时更新信息类 有功电度
    # (0x0048, 4),  # 实时更新信息类 无功电度
    (0x0200, 10),  # 系统参数寄存器 PT CT
    (0x0300, 26),  # 开入参数寄存器
    (0x0400, 41),  # 出口参数寄存器
    (0x0600, 35),  # 通信参数寄存器
    (0x0700, 8),  # 产品信息寄存器
    (0x0800, 76),  # 保护整定寄存器
    (0x0E40, 32),  # 保护通道校正系数寄存器
)

DISCT_WO = (
    (0x0910, 6),  # 事件信息交互功能寄存器
    (0x0B00, 2),  # 遥控出口寄存器
    (0x0B20, 5),  # 系统控制寄存器
    (0x0E20, 4),  # 调试控制寄存器
    (0x0E70, 8),  # 开出调试寄存器
    (0x0E90, 17),  # 交流量旁路通道控制寄存器
)

TAB_SEND_QUEUE = (
    ((0x0000, 92), (0x0900, 4), (0x0920, 10)),
    ((0x0000, 5), (0x0900, 4), (0x0920, 10), (0x0040, 16), (0x0200, 10), (0x0600, 35), (0x0700, 8), (0x0900, 4)),
    ((0x0900, 4), (0x0920, 10), (0x0300, 26), (0x0400, 41)),
    ((0x0900, 4), (0x0920, 10), (0x040A, 31), (0x0800, 47)),
    ((0x0900, 4), (0x0920, 10), (0x040A, 31), (0x082F, 28)),
    ((0x030D, 12), (0x0900, 4), (0x0900, 4), (0x0920, 10)),
    ((0x0900, 4), (0x0920, 10), (0x0E00, 8)),
    ((0x0004, 6), (0x000E, 19), (0x0900, 4), (0x0920, 10), (0x0E40, 32)),
    ((0x0900, 4), (0x0920, 10), (0x000E, 8), (0x0023, 33), (0x0700, 8)),
)


DI_FUNC_TYPE = (
    "普通开入",
    "断路器合位",
    "断路器分位",
    "隔离刀闸合位",
    "隔离刀闸分位",
    "接地刀闸合位",
    "接地刀闸分位",
    "手车工作位置",
    "手车试验位置",
    "弹簧未储能",
    "弹簧已储能",
    "变压器开门",
    "重瓦斯",
    "轻瓦斯",
    "超温",
    "高温",
    "压力释放",
    "闭锁重合闸",
    "远方控制",
    "非电量1",
    "非电量2",
    "复归",
    "检修",
)

DO_PRT_TYPE_NAME = (
    "过流1段保护",
    "过流2段保护",
    "过流3段保护",
    "反时限保护",
    "零序1段保护",
    "零序2段保护",
    "负序过流保护",
    "过负荷保护",
    "低电压保护",
    "过电压保护",
    "不平衡电流保护",
    "不平衡电压保护",
    "充电保护",
    "重合闸保护",
    "后加速保护",
    "过热保护",
    "启动速断保护",
    "启动超时保护",
    "堵转保护",
    "重瓦斯保护",
    "轻瓦斯保护",
    "高温保护",
    "超温保护",
    "压力释放保护",
    "非电量1保护",
    "非电量2保护",
    "PT断线信号",
    "遥合信号",
    "遥跳信号",
)
PRT_STATUS_TYPE_NAME = (
    "过流1段保护",
    "过流2段保护",
    "过流3段保护",
    "反时限保护",
    "零序1段保护",
    "零序2段保护",
    "负序过流保护",
    "过负荷保护",
    "低电压保护",
    "过电压保护",
    "不平衡电流保护",
    "不平衡电压保护",
    "充电保护",
    "重合闸保护",
    "后加速保护",
    "过热保护",
    "启动速断保护",
    "启动超时保护",
    "堵转保护",
    "重瓦斯信号",
    "轻瓦斯信号",
    "高温信号",
    "超温信号",
    "压力释放信号",
    "非电量1信号",
    "非电量2信号",
    "PT断线信号",
)

DI_NUM = 12
DO_NUM = 10
DO_NUM_WITHOUT_LED = 8
DO_NAME = ("开出1", "开出2", "开出3", "开出4", "开出5", "开出6", "开出7", "开出8", "动作灯", "告警灯")


PHASE_NAME = ("None", "Ia", "Ib", "Ic", "Uab", "Ubc", "Uca", "3I0", "Ix")
UNIT_NAME = ("A", "V")


def eventPtrActDecode(data: int):
    """保护事件动作值数据解析 int-->str"""
    unit = ""
    rate = 2
    typePrt = data[0]
    phasePrt = data[2]
    valuePrt = data[3]
    specIdx = -1
    if phasePrt > 0:  # 有相别
        outName = PHASE_NAME[phasePrt]
        if phasePrt == 7:
            specIdx = 8
        else:
            specIdx = phasePrt - 1
        if phasePrt in (1, 2, 3, 7, 8):
            unit = "A"
        else:
            unit = "V"
    elif phasePrt == 0:  # 无相别
        if typePrt in (0x0004, 0x0010):  # 反时限 过热
            outName = "热容"
            rate = 4
            if typePrt == 0x0004:
                specIdx = 12
            else:
                specIdx = 11
        elif typePrt in (0x0005, 0x0006):  # 零序 1 2 电流
            outName = "I0"
            unit = "A"
            specIdx = 8
        elif typePrt == 0x0007:  # 负序电流
            outName = "I2"
            unit = "A"
            specIdx = 10
        elif typePrt == 0x000B:  # 不平衡电流
            outName = "Ix"
            unit = "A"
            specIdx = 6
        elif typePrt == 0x000C:  # 不平衡电压
            outName = "Ux"
            unit = "V"
            specIdx = 7
        else:
            outName = None
    if outName is None:
        return "无动作值", specIdx
    else:

        return "{}: {:.{}f}{}".format(outName, valuePrt / (10 ** rate), rate, unit), specIdx


def eventPtrDetailDecode(data: int):
    """保护事件特征值数据解析 int-->str"""
    newData = []
    for i, d in enumerate(data):
        if i in (11, 12):
            newData.append(d / 10000)
        else:
            newData.append(d / 100)
    units = ("A", "A", "A", "V", "V", "V", "A", "V", "A", "A", "A", "", "")
    fonts = (".2f", ".2f", ".2f", ".2f", ".2f", ".2f", ".2f", ".2f", ".2f", ".2f", ".2f", ".4f", ".4f")
    for d, font, unit in zip(newData, fonts, units):
        yield "{:{}}{}".format(d, font, unit)


# 过流1段保护投退定值     3
# 过流2段保护投退定值     3
# 过流3段保护投退定值     3
# 反时限保护投退定值      5
# 零序1段保护投退定值     3
# 零序2段保护投退定值     3
# 负序过流保护投退定值    3
# 过负荷保护投退定值      3
# 低电压保护投退定值      3
# 过电压保护投退定值      3
# 不平衡电流保护投退定值  3
# 不平衡电压保护投退定值  3
# 充电保护投退定值        4
# 重合闸保护投退定值      2
# 后加速保护投退定值      3
# 电动机保护投退          3
# 过热保护投退定值        3
# 启动速断保护投退定值    3
# 启动超时保护投退定值    1
# 堵转保护投退定值        3
# 重瓦斯保护投退定值      2
# 轻瓦斯保护投退定值      2
# 高温段保护投退定值      2
# 超温保护投退定值        2
# 压力释放保投退定值      2
# 非电量1保护投退定值     2
# 非电量2保护投退定值     2
# PT断线保护投退定值      1


ProtectSubWidgetConf = namedtuple(
    "ProtectSubWidgetConf", "index num range name itemNames unitNames groupPlace doSelectIndex"
)
PTR_SUB_CONFS = (
    ProtectSubWidgetConf(
        0, 3, ((0.10, 100.00), (0.00, 99.99)), "过流1段保护", ("电流定值", "时间定值"), ("A", "S"), (0, 0, 3, 1), 0
    ),
    ProtectSubWidgetConf(
        3, 3, ((0.10, 100.00), (0.00, 99.99)), "过流2段保护", ("电流定值", "时间定值"), ("A", "S"), (0, 1, 3, 1), 1
    ),
    ProtectSubWidgetConf(
        6, 3, ((0.10, 100.00), (0.00, 99.99)), "过流3段保护", ("电流定值", "时间定值"), ("A", "S"), (0, 2, 3, 1), 2
    ),
    ProtectSubWidgetConf(
        9,
        5,
        ((0.10, 20.00), (0.05, 15.00), (1, 3), (1.00, 4.00)),
        "反时限保护",
        ("基准电流", "时间常数", "保护曲线", "启动倍数"),
        ("A", "S", "", ""),
        (6, 0, 3, 1),
        3,
    ),
    ProtectSubWidgetConf(
        14, 3, ((0.01, 100.00), (0.00, 99.99)), "零序1段保护", ("电流定值", "时间定值"), ("A", "S"), (0, 3, 3, 1), 4
    ),
    ProtectSubWidgetConf(
        17, 3, ((0.01, 100.00), (0.00, 99.99)), "零序2段保护", ("电流定值", "时间定值"), ("A", "S"), (0, 4, 3, 1), 5
    ),
    ProtectSubWidgetConf(
        20, 3, ((0.10, 100.00), (0.00, 99.99)), "负序过流保护", ("电流定值", "时间定值"), ("A", "S"), (3, 0, 3, 1), 6
    ),
    ProtectSubWidgetConf(
        23, 3, ((0.10, 100.00), (0.00, 600.00)), "过负荷保护", ("电流定值", "时间定值"), ("A", "S"), (3, 1, 3, 1), 7
    ),
    ProtectSubWidgetConf(
        26, 3, ((10.00, 350.00), (0.00, 99.99)), "低电压保护", ("电压定值", "时间定值"), ("V", "S"), (3, 2, 3, 1), 8
    ),
    ProtectSubWidgetConf(
        29, 3, ((100.00, 460.00), (0.00, 99.99)), "过电压保护", ("电压定值", "时间定值"), ("V", "S"), (3, 3, 3, 1), 9
    ),
    ProtectSubWidgetConf(
        32, 3, ((0.10, 20.00), (0.00, 99.99)), "不平衡电流保护", ("电流定值", "时间定值"), ("A", "S"), (6, 2, 3, 1), 10
    ),
    ProtectSubWidgetConf(
        35, 3, ((2.00, 460.00), (0.00, 99.99)), "不平衡电压保护", ("电压定值", "时间定值"), ("V", "S"), (3, 4, 3, 1), 11
    ),
    ProtectSubWidgetConf(
        38,
        4,
        ((0.00, 10.00), (0.10, 100.00), (0.00, 5.00)),
        "充电保护",
        ("加速时间", "动作电流", "动作时间"),
        ("S", "A", "S"),
        (6, 1, 3, 1),
        12,
    ),
    ProtectSubWidgetConf(42, 2, ((0.00, 10.00),), "重合闸保护", ("时间定值",), ("S",), (6, 4, 2, 1), 13),
    ProtectSubWidgetConf(
        44, 3, ((0.00, 100.00), (0.00, 5.00)), "后加速保护", ("电流定值", "时间定值"), ("A", "S"), (6, 3, 3, 1), 14
    ),
    ProtectSubWidgetConf(
        47, 3, ((0.10, 100.00), (0.00, 99.99)), "电动机", ("额定电流", "启动时间"), ("A", "S"), (0, 0, 3, 1), None
    ),
    ProtectSubWidgetConf(50, 3, ((0, 6000), (3.00, 10.00)), "过热保护", ("发热时间", "负序系数"), ("S", ""), (0, 1, 3, 1), 15),
    ProtectSubWidgetConf(
        53, 3, ((0.10, 100.00), (0.00, 99.99)), "启动速断保护", ("电流定值", "时间定值"), ("A", "S"), (0, 2, 3, 1), 16
    ),
    ProtectSubWidgetConf(56, 1, (), "启动超时保护", (), (), (0, 3, 3, 1), 17),
    ProtectSubWidgetConf(
        57, 3, ((0.10, 100.00), (0.00, 99.99)), "堵转保护", ("电流定值", "时间定值"), ("A", "S"), (0, 4, 3, 1), 18
    ),
    ProtectSubWidgetConf(60, 2, ((0.00, 99.99),), "重瓦斯保护", ("时间定值",), ("S",), (3, 0, 3, 1), 19),
    ProtectSubWidgetConf(62, 2, ((0.00, 99.99),), "轻瓦斯保护", ("时间定值",), ("S",), (3, 1, 3, 1), 20),
    ProtectSubWidgetConf(64, 2, ((0.00, 99.99),), "高温段保护", ("时间定值",), ("S",), (3, 2, 3, 1), 21),
    ProtectSubWidgetConf(66, 2, ((0.00, 99.99),), "超温保护", ("时间定值",), ("S",), (3, 3, 3, 1), 22),
    ProtectSubWidgetConf(68, 2, ((0.00, 99.99),), "压力释放保", ("时间定值",), ("S",), (3, 4, 3, 1), 23),
    ProtectSubWidgetConf(70, 2, ((0.00, 99.99),), "非电量1保护", ("时间定值",), ("S",), (6, 0, 3, 1), 24),
    ProtectSubWidgetConf(72, 2, ((0.00, 99.99),), "非电量2保护", ("时间定值",), ("S",), (6, 1, 3, 1), 25),
    ProtectSubWidgetConf(74, 1, (), "PT断线保护", (), (), (6, 2, 1, 1), 26),
)

Mea_3I0_C_NAMES = ("内部合成", "外部采集")
Mea_LN_NAMES = ("三相三线", "三相四线")

COMM_BAUD_LIST = ("1200", "2400", "4800", "9600", "19200")

PrtUI_Conf = namedtuple("PrtUI_Conf", "name format rate unit toleranceIndex")
PRT_UI_CONFS = (
    PrtUI_Conf("Uab", "6.2f", 100, "V", 0),
    PrtUI_Conf("Ubc", "6.2f", 100, "V", 1),
    PrtUI_Conf("Uca", "6.2f", 100, "V", 2),
    PrtUI_Conf("IA", "6.2f", 100, "A", 6),
    PrtUI_Conf("IB", "6.2f", 100, "A", 7),
    PrtUI_Conf("IC", "6.2f", 100, "A", 8),
    PrtUI_Conf("UX", "6.2f", 100, "V", 12),
    PrtUI_Conf("IX", "6.2f", 100, "A", 13),
    PrtUI_Conf("3I0", "6.2f", 100, "A", -1),
    PrtUI_Conf("I1", "6.2f", 100, "A", -1),
    PrtUI_Conf("I2", "6.2f", 100, "A", -1),
    PrtUI_Conf("过热", "6.4f", 10000, "", -1),
    PrtUI_Conf("反时限", "6.4f", 10000, "", -1),
    PrtUI_Conf("φ Uab", "6.1f", 10, "°", 3),
    PrtUI_Conf("φ Ubc", "6.1f", 10, "°", 4),
    PrtUI_Conf("φ Uca", "6.1f", 10, "°", 5),
    PrtUI_Conf("φ IA", "6.1f", 10, "°", 9),
    PrtUI_Conf("φ IB", "6.1f", 10, "°", 10),
    PrtUI_Conf("φ IC", "6.1f", 10, "°", 11),
)

MeaUI_Conf = namedtuple("MeaUI_Conf", "name format rate unit")
MEA_UI_CONFS = (
    MeaUI_Conf("IA", "6.3f", 1000, "A"),
    MeaUI_Conf("IB", "6.3f", 1000, "A"),
    MeaUI_Conf("IC", "6.3f", 1000, "A"),
    MeaUI_Conf("平均值", "6.3f", 1000, "A"),
    MeaUI_Conf("UA", "6.2f", 100, "V"),
    MeaUI_Conf("UB", "6.2f", 100, "V"),
    MeaUI_Conf("UC", "6.2f", 100, "V"),
    MeaUI_Conf("平均值", "6.2f", 100, "V"),
    MeaUI_Conf("UAB", "6.2f", 100, "A"),
    MeaUI_Conf("UBC", "6.2f", 100, "V"),
    MeaUI_Conf("UCA", "6.2f", 100, "V"),
    MeaUI_Conf("平均值", "6.2f", 100, "V"),
    MeaUI_Conf("η A", "6.3f", 1000, ""),
    MeaUI_Conf("η B", "6.3f", 1000, ""),
    MeaUI_Conf("η C", "6.3f", 1000, ""),
    MeaUI_Conf("平均值", "6.3f", 1000, ""),
    MeaUI_Conf("频率", "6.2f", 100, "Hz"),
    MeaUI_Conf("PA", ".3f", 1000, "W"),
    MeaUI_Conf("PB", ".3f", 1000, "W"),
    MeaUI_Conf("PC", ".3f", 1000, "W"),
    MeaUI_Conf("总有功", ".3f", 1000, "W"),
    MeaUI_Conf("QA", ".3f", 1000, "Var"),
    MeaUI_Conf("QB", ".3f", 1000, "Var"),
    MeaUI_Conf("QC", ".3f", 1000, "Var"),
    MeaUI_Conf("总无功", ".3f", 1000, "Var"),
    MeaUI_Conf("SA", ".3f", 1000, "VA"),
    MeaUI_Conf("SB", ".3f", 1000, "VA"),
    MeaUI_Conf("SC", ".3f", 1000, "VA"),
    MeaUI_Conf("总视在", ".3f", 1000, "VA"),
    MeaUI_Conf("正向", ".1f", 10, "kWh"),
    MeaUI_Conf("负向", ".1f", 10, "kWh"),
    MeaUI_Conf("总量", ".1f", 10, "kWh"),
    MeaUI_Conf("净值", ".1f", 10, "kWh"),
    MeaUI_Conf("正向", ".1f", 10, "kVarh"),
    MeaUI_Conf("负向", ".1f", 10, "kVarh"),
    MeaUI_Conf("总量", ".1f", 10, "kVarh"),
    MeaUI_Conf("净值", ".1f", 10, "kVarh"),
)

BypassConf = namedtuple("BypassConf", "name range decimal singleStep unit modbusAddr checked")
BYPASS_CONFS = (
    BypassConf("线电压Uab有效值", (0.00, 655.35), 2, 0.1, "V", 0x000E, True),
    BypassConf("线电压Uab相角", (0.0, 360.0), 1, 0.1, "°", 0x001B, False),
    BypassConf("线电压Ubc有效值", (0.00, 655.35), 2, 0.1, "V", 0x000F, True),
    BypassConf("线电压Uab相角", (0.0, 360.0), 1, 0.1, "°", 0x001C, False),
    BypassConf("线电压Uca有效值", (0.00, 655.35), 2, 0.1, "V", 0x0010, True),
    BypassConf("线电压Uca相角", (0.0, 360.0), 1, 0.1, "°", 0x001D, False),
    BypassConf("A相电流有效值", (0.00, 655.35), 2, 0.05, "A", 0x0011, True),
    BypassConf("A相电流相角", (0.0, 360.0), 1, 0.1, "°", 0x001E, False),
    BypassConf("B相电流有效值", (0.00, 655.35), 2, 0.05, "A", 0x0012, True),
    BypassConf("B相电流相角", (0.0, 360.0), 1, 0.1, "°", 0x001F, False),
    BypassConf("C相电流有效值", (0.00, 655.35), 2, 0.05, "A", 0x0013, True),
    BypassConf("C相电流相角", (0.0, 360.0), 1, 0.1, "°", 0x0020, False),
    BypassConf("电压UX有效值", (0.00, 655.35), 2, 0.1, "V", 0x0014, True),
    BypassConf("电流IX有效值", (0.00, 655.35), 2, 0.1, "A", 0x0015, True),
    BypassConf("自产合成3I0", (0.00, 655.35), 2, 0.1, "A", 0x0016, True),
    BypassConf("正序电流I1", (0.00, 655.35), 2, 0.1, "A", 0x0017, True),
    BypassConf("负序电流I2", (0.00, 655.35), 2, 0.1, "A", 0x0018, True),
)

AUTO_ADUJST_NAME = ("电流校正", "电压校正", "IX电流校正", "UX电压校正")
AdjustValueConf = namedtuple("AdjustValueConf", "name range decimal singleStep")
ADJUST_VALUE_CONFS = (
    AdjustValueConf("IA幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("IA相角", (0.0, 360.0), 1, 1),
    AdjustValueConf("IB幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("IB相角", (0.0, 360.0), 1, 1),
    AdjustValueConf("IC幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("IC相角", (0.0, 360.0), 1, 1),
    AdjustValueConf("UAB幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("UAB相角", (0.0, 360.0), 1, 1),
    AdjustValueConf("UBC幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("UBC相角", (0.0, 360.0), 1, 1),
    AdjustValueConf("UCA幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("UCA相角", (0.0, 360.0), 1, 1),
    AdjustValueConf("IX幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("IX相角", (0.0, 360.0), 1, 1),
    AdjustValueConf("UX幅值", (0.5, 1.5), 3, 0.01),
    AdjustValueConf("UX相角", (0.0, 360.0), 1, 1),
)


FAULT_NAME_TYPE_1 = (
    "上电自检故障",
    "AD硬件故障",
    "Ia电流通道故障",
    "Ia电流通道故障",
    "Ia电流通道故障",
    "Ilx电流通道故障",
    "Uab电压通道故障",
    "Ubc电压通道故障",
    "Uca电压通道故障",
    "Ulx电压通道故障",
    "系统时钟硬件错误",
    "片内FLASH读取错误",
    "片内FLASH写入错误",
    "片外EEPROM读取错误",
    "片外EEPROM写入错误",
    "以太网1硬件错误",
    "以太网1通信中断",
    "以太网2硬件错误",
    "以太网2通信中断",
    "RS485_1通信中断",
    "RS485_2通信中断",
    "计量通信中断",
    "计量模块故障",
    "时间错误码",
    "动态内存1不足",
    "动态内存2不足",
    "动态内存3不足",
    "自动校正失败",
    "断路器状态错误",
)

FAULT_NAME_TYPE_2 = (
    "串口通信参数错误",
    "网口通信参数错误",
    "开入参数错误",
    "开出参数错误",
    "设备信息错误",
    "系统参数错误",
    "校正参数错误",
    "保护参数错误",
    "保护事件数据错误",
    "遥信事件数据错误",
)

FAULT_NAME_TYPE_3 = (
    "电流1段保护",
    "电流2段保护",
    "电流3段保护",
    "反时限保护",
    "零序1段保护",
    "零序2段保护",
    "负序过流保护",
    "过负荷保护",
    "低电压保护",
    "过电压保护",
    "不平衡电流保护",
    "不平衡电压保护",
    "充电保护",
    "重合闸保护",
    "后加速保护",
    "过热保护",
    "启动速断保护",
    "启动超时保护",
    "堵转保护",
    "重瓦斯保护",
    "轻瓦斯保护",
    "高温保护",
    "超温段保护",
    "压力释放保护",
    "非电量1保护",
    "非电量2保护",
    "电动机相关保护",
    "PT断线保护",
)

FAULT_NAME_TYPE_4 = (
    "电流1段保护动作",
    "电流2段保护动作",
    "电流3段保护动作",
    "反时限保护动作",
    "零序1段保护动作",
    "零序2段保护动作",
    "负序过流保护动作",
    "过负荷保护动作",
    "低电压保护动作",
    "过电压保护动作",
    "不平衡电流保护动作",
    "不平衡电压保护动作",
    "充电保护动作",
    "重合闸保护动作",
    "后加速保护动作",
    "过热保护动作",
    "启动速断保护动作",
    "启动超时保护动作",
    "堵转保护动作",
    "重瓦斯保护动作",
    "轻瓦斯保护动作",
    "高温保护动作",
    "超温段保护动作",
    "压力释放保护动作",
    "非电量1保护动作",
    "非电量2保护动作",
    "PT断线保护动作",
    "遥控合闸动作",
    "遥控跳闸动作",
)

FAULT_NAME = (FAULT_NAME_TYPE_1, FAULT_NAME_TYPE_2, FAULT_NAME_TYPE_3, FAULT_NAME_TYPE_4)
FAULT_GROUP_NAME = ("硬件故障", "系统参数", "保护参数", "保护动作")

ROOT_3 = 3 ** 0.5
ReportMeasureConf = namedtuple("MeasureConf", "name unit rate format dataAddress toleranceType signed")
REPORT_PRT_CONFS = (
    ReportMeasureConf("Uab", "V", 100, "6.2f", 0x000E, "percent", False),
    ReportMeasureConf("Ubc", "V", 100, "6.2f", 0x000F, "percent", False),
    ReportMeasureConf("Uca", "V", 100, "6.2f", 0x0010, "percent", False),
    ReportMeasureConf("Ia", "A", 100, "6.2f", 0x0011, "percent", False),
    ReportMeasureConf("Ib", "A", 100, "6.2f", 0x0012, "percent", False),
    ReportMeasureConf("Ic", "A", 100, "6.2f", 0x0013, "percent", False),
    ReportMeasureConf("UX", "V", 100, "6.2f", 0x0014, "percent", False),
    ReportMeasureConf("Ix", "A", 100, "6.2f", 0x0015, "percent", False),
)

REPORT_MEA_CONFS = (
    ReportMeasureConf("Ia", "A", 1000, "6.3f", (0x0023, ), "percent", False),
    ReportMeasureConf("Ib", "A", 1000, "6.3f", (0x0024, ), "percent", False),
    ReportMeasureConf("Ic", "A", 1000, "6.3f", (0x0025, ), "percent", False),
    ReportMeasureConf("Ua", "V", 100, "6.2f", (0x0027, ), "percent", False),
    ReportMeasureConf("Ub", "V", 100, "6.2f", (0x0028, ), "percent", False),
    ReportMeasureConf("Uc", "V", 100, "6.2f", (0x0029, ), "percent", False),
    ReportMeasureConf("Pa", "W", 1000, "6.3f", (0x0034, 0x0035), "percent", True),
    ReportMeasureConf("Pb", "W", 1000, "6.3f", (0x0036, 0x0037), "percent", True),
    ReportMeasureConf("Pc", "W", 1000, "6.3f", (0x0038, 0x0039), "percent", True),
    ReportMeasureConf("Qa", "Var", 1000, "6.3f", (0x003c, 0x003d), "percent", True),
    ReportMeasureConf("Qb", "Var", 1000, "6.3f", (0x003e, 0x003f), "percent", True),
    ReportMeasureConf("Qc", "Var", 1000, "6.3f", (0x0040, 0x0041), "percent", True),
    ReportMeasureConf("COSa", "", 1000, "+6.3f", (0x002F, ), "absolute", True),
    ReportMeasureConf("COSb", "", 1000, "+6.3f", (0x0030, ), "absolute", True),
    ReportMeasureConf("COSc", "", 1000, "+6.3f", (0x0030, ), "absolute", True),
    ReportMeasureConf("COS", "", 1000, "+6.3f", (0x0031, ), "absolute", True),
    ReportMeasureConf("Fq", "Hz", 100, "6.2f", (0x0033, ), "absolute", False),
)

ReportDataTableConf = namedtuple("ReportDataTableConf", "rowNames columnNames")
ReportDataTableItemConf = namedtuple("ReportDataTableItemConf", "row column keyName manten goukaku")

REPORT_PRT_TABLE_CONF = ReportDataTableConf(("1", "2", "3", "4"), ("Ia", "Ib", "Ic", "Uab", "Ubc", "Uca", "Ix", "Ux"))
REPORT_PRT_TABLE_ITEM_CONF = (
    ReportDataTableItemConf(0, 0, "prt_ia_1", 0.5, (0.98, 1.02)),
    ReportDataTableItemConf(1, 0, "prt_ia_2", 8, (0.98, 1.02)),
    ReportDataTableItemConf(2, 0, "prt_ia_3", 12, (0.98, 1.02)),
    ReportDataTableItemConf(3, 0, "prt_ia_4", 20, (0.98, 1.02)),
    ReportDataTableItemConf(0, 1, "prt_ib_1", 0.5, (0.98, 1.02)),
    ReportDataTableItemConf(1, 1, "prt_ib_2", 8, (0.98, 1.02)),
    ReportDataTableItemConf(2, 1, "prt_ib_3", 12, (0.98, 1.02)),
    ReportDataTableItemConf(3, 1, "prt_ib_4", 20, (0.98, 1.02)),
    ReportDataTableItemConf(0, 2, "prt_ic_1", 0.5, (0.98, 1.02)),
    ReportDataTableItemConf(1, 2, "prt_ic_2", 8, (0.98, 1.02)),
    ReportDataTableItemConf(2, 2, "prt_ic_3", 12, (0.98, 1.02)),
    ReportDataTableItemConf(3, 2, "prt_ic_4", 20, (0.98, 1.02)),
    ReportDataTableItemConf(0, 3, "prt_uab_1", 30, (0.98, 1.02)),
    ReportDataTableItemConf(1, 3, "prt_uab_2", 120, (0.98, 1.02)),
    ReportDataTableItemConf(2, 3, "prt_uab_3", 160, (0.98, 1.02)),
    ReportDataTableItemConf(3, 3, "prt_uab_4", 450, (0.98, 1.02)),
    ReportDataTableItemConf(0, 4, "prt_ubc_1", 30, (0.98, 1.02)),
    ReportDataTableItemConf(1, 4, "prt_ubc_2", 120, (0.98, 1.02)),
    ReportDataTableItemConf(2, 4, "prt_ubc_3", 160, (0.98, 1.02)),
    ReportDataTableItemConf(3, 4, "prt_ubc_4", 450, (0.98, 1.02)),
    ReportDataTableItemConf(0, 5, "prt_uca_1", 30, (0.98, 1.02)),
    ReportDataTableItemConf(1, 5, "prt_uca_2", 120, (0.98, 1.02)),
    ReportDataTableItemConf(2, 5, "prt_uca_3", 160, (0.98, 1.02)),
    ReportDataTableItemConf(3, 5, "prt_uca_4", 450, (0.98, 1.02)),
    ReportDataTableItemConf(0, 6, "prt_ix_1", 0.5, (0.98, 1.02)),
    ReportDataTableItemConf(1, 6, "prt_ix_2", 8, (0.98, 1.02)),
    ReportDataTableItemConf(2, 6, "prt_ix_3", 12, (0.98, 1.02)),
    ReportDataTableItemConf(3, 6, "prt_ix_4", 20, (0.98, 1.02)),
    ReportDataTableItemConf(0, 7, "prt_ux_1", 30, (0.98, 1.02)),
    ReportDataTableItemConf(1, 7, "prt_ux_2", 120, (0.98, 1.02)),
    ReportDataTableItemConf(2, 7, "prt_ux_3", 160, (0.98, 1.02)),
    ReportDataTableItemConf(3, 7, "prt_ux_4", 450, (0.98, 1.02)),
)

REPORT_PRT_TABLE_CONF_FILE_PATH = "./config/spac800_prt_table.json"
if os.path.exists(REPORT_PRT_TABLE_CONF_FILE_PATH) and os.path.isfile(REPORT_PRT_TABLE_CONF_FILE_PATH):
    try:
        with open(REPORT_PRT_TABLE_CONF_FILE_PATH, "r") as f:
            dd = json.load(f)
        REPORT_PRT_TABLE_ITEM_CONF = [ReportDataTableItemConf(**i) for i in dd]
    except Exception:
        print(stackprinter.format())
else:
    try:
        basedir = os.path.dirname(os.path.abspath(REPORT_PRT_TABLE_CONF_FILE_PATH))
        os.makedirs(basedir, exist_ok=True)
        with open(REPORT_PRT_TABLE_CONF_FILE_PATH, "w", encoding="utf-8") as f:
            json.dump([ob._asdict() for ob in REPORT_PRT_TABLE_ITEM_CONF], f, ensure_ascii=False, indent=4)
    except Exception:
        print(stackprinter.format())


REPORT_MEA_TABLE_I_CONF = ReportDataTableConf(("1", "2", "3", "4"), ("Ia", "Ib", "Ic"))
REPORT_MEA_TABLE_U_CONF = ReportDataTableConf(("1", "2", "3", "4"), ("Ua", "Ub", "Uc"))
REPORT_MEA_TABLE_PQ_CONF = ReportDataTableConf(("1", "2"), ("Pa", "Pb", "Pc", "Qa", "Qb", "Qc", "Cos"))

REPORT_MEA_TABLE_CONFS = (REPORT_MEA_TABLE_I_CONF, REPORT_MEA_TABLE_U_CONF, REPORT_MEA_TABLE_PQ_CONF)

REPORT_MEA_TABLE_I_ITEM_CONF = (
    ReportDataTableItemConf(0, 0, "mea_ia_1", 0.5, (0.995, 1.005)),
    ReportDataTableItemConf(1, 0, "mea_ia_2", 2.5, (0.995, 1.005)),
    ReportDataTableItemConf(2, 0, "mea_ia_3", 5.0, (0.995, 1.005)),
    ReportDataTableItemConf(3, 0, "mea_ia_4", 6.0, (0.995, 1.005)),
    ReportDataTableItemConf(0, 1, "mea_ib_1", 0.5, (0.995, 1.005)),
    ReportDataTableItemConf(1, 1, "mea_ib_2", 2.5, (0.995, 1.005)),
    ReportDataTableItemConf(2, 1, "mea_ib_3", 5.0, (0.995, 1.005)),
    ReportDataTableItemConf(3, 1, "mea_ib_4", 6.0, (0.995, 1.005)),
    ReportDataTableItemConf(0, 2, "mea_ic_1", 0.5, (0.995, 1.005)),
    ReportDataTableItemConf(1, 2, "mea_ic_2", 2.5, (0.995, 1.005)),
    ReportDataTableItemConf(2, 2, "mea_ic_3", 5.0, (0.995, 1.005)),
    ReportDataTableItemConf(3, 2, "mea_ic_4", 6.0, (0.995, 1.005)),
)
REPORT_MEA_TABLE_I_ITEM_CONF_FILE_PATH = "./config/idin201f_i_table.json"
if os.path.exists(REPORT_MEA_TABLE_I_ITEM_CONF_FILE_PATH) and os.path.isfile(REPORT_MEA_TABLE_I_ITEM_CONF_FILE_PATH):
    try:
        with open(REPORT_MEA_TABLE_I_ITEM_CONF_FILE_PATH, "r") as f:
            dd = json.load(f)
        REPORT_MEA_TABLE_I_ITEM_CONF = [ReportDataTableItemConf(**i) for i in dd]
    except Exception:
        print(stackprinter.format())
else:
    try:
        basedir = os.path.dirname(os.path.abspath(REPORT_MEA_TABLE_I_ITEM_CONF_FILE_PATH))
        os.makedirs(basedir, exist_ok=True)
        with open(REPORT_MEA_TABLE_I_ITEM_CONF_FILE_PATH, "w", encoding="utf-8") as f:
            json.dump([ob._asdict() for ob in REPORT_MEA_TABLE_I_ITEM_CONF], f, ensure_ascii=False, indent=4)
    except Exception:
        print(stackprinter.format())

REPORT_MEA_TABLE_U_ITEM_CONF = (
    ReportDataTableItemConf(0, 0, "mea_ua_1", 30, (0.995, 1.005)),
    ReportDataTableItemConf(1, 0, "mea_ua_2", 100, (0.995, 1.005)),
    ReportDataTableItemConf(2, 0, "mea_ua_3", 220, (0.995, 1.005)),
    ReportDataTableItemConf(3, 0, "mea_ua_4", 250, (0.995, 1.005)),
    ReportDataTableItemConf(0, 1, "mea_ub_1", 30, (0.995, 1.005)),
    ReportDataTableItemConf(1, 1, "mea_ub_2", 100, (0.995, 1.005)),
    ReportDataTableItemConf(2, 1, "mea_ub_3", 220, (0.995, 1.005)),
    ReportDataTableItemConf(3, 1, "mea_ub_4", 250, (0.995, 1.005)),
    ReportDataTableItemConf(0, 2, "mea_uc_1", 30, (0.995, 1.005)),
    ReportDataTableItemConf(1, 2, "mea_uc_2", 100, (0.995, 1.005)),
    ReportDataTableItemConf(2, 2, "mea_uc_3", 220, (0.995, 1.005)),
    ReportDataTableItemConf(3, 2, "mea_uc_4", 250, (0.995, 1.005)),
)
REPORT_MEA_TABLE_U_ITEM_CONF_FILE_PATH = "./config/idin201f_u_table.json"
if os.path.exists(REPORT_MEA_TABLE_U_ITEM_CONF_FILE_PATH) and os.path.isfile(REPORT_MEA_TABLE_U_ITEM_CONF_FILE_PATH):
    try:
        with open(REPORT_MEA_TABLE_U_ITEM_CONF_FILE_PATH, "r") as f:
            dd = json.load(f)
        REPORT_MEA_TABLE_U_ITEM_CONF = [ReportDataTableItemConf(**i) for i in dd]
    except Exception:
        print(stackprinter.format())
else:
    try:
        basedir = os.path.dirname(os.path.abspath(REPORT_MEA_TABLE_U_ITEM_CONF_FILE_PATH))
        os.makedirs(basedir, exist_ok=True)
        with open(REPORT_MEA_TABLE_U_ITEM_CONF_FILE_PATH, "w", encoding="utf-8") as f:
            json.dump([ob._asdict() for ob in REPORT_MEA_TABLE_U_ITEM_CONF], f, ensure_ascii=False, indent=4)
    except Exception:
        print(stackprinter.format())

REPORT_MEA_TABLE_PQ_ITEM_CONF = (
    ReportDataTableItemConf(0, 0, "mea_pa_1", 100 * 2.5 * math.cos(math.radians(60)), (0.994, 1.006)),
    ReportDataTableItemConf(0, 1, "mea_pb_1", 100 * 2.5 * math.cos(math.radians(60)), (0.994, 1.006)),
    ReportDataTableItemConf(0, 2, "mea_pc_1", 100 * 2.5 * math.cos(math.radians(60)), (0.994, 1.006)),
    ReportDataTableItemConf(0, 3, "mea_qa_1", 100 * 2.5 * math.cos(math.radians(60)), (0.98, 1.02)),
    ReportDataTableItemConf(0, 4, "mea_qb_1", 100 * 2.5 * math.cos(math.radians(60)), (0.98, 1.02)),
    ReportDataTableItemConf(0, 5, "mea_qc_1", 100 * 2.5 * math.cos(math.radians(60)), (0.98, 1.02)),
    ReportDataTableItemConf(0, 6, "mea_cos_1", 1.0, (0.495, 0.505)),
    ReportDataTableItemConf(1, 0, "mea_pa_2", 220 * 5 * math.sin(math.radians(60)), (0.995, 1.005)),
    ReportDataTableItemConf(1, 1, "mea_pb_2", 220 * 5 * math.sin(math.radians(60)), (0.995, 1.005)),
    ReportDataTableItemConf(1, 2, "mea_pc_2", 220 * 5 * math.sin(math.radians(60)), (0.995, 1.005)),
    ReportDataTableItemConf(1, 3, "mea_qa_2", 220 * 5 * math.sin(math.radians(60)), (0.98, 1.02)),
    ReportDataTableItemConf(1, 4, "mea_qb_2", 220 * 5 * math.sin(math.radians(60)), (0.98, 1.02)),
    ReportDataTableItemConf(1, 5, "mea_qc_2", 220 * 5 * math.sin(math.radians(60)), (0.98, 1.02)),
    ReportDataTableItemConf(1, 6, "mea_cos_2", 1.0, (0.495, 0.505)),
)
REPORT_MEA_TABLE_PQ_ITEM_CONF_FILE_PATH = "./config/idin201f_pq_table.json"
if os.path.exists(REPORT_MEA_TABLE_PQ_ITEM_CONF_FILE_PATH) and os.path.isfile(REPORT_MEA_TABLE_PQ_ITEM_CONF_FILE_PATH):
    try:
        with open(REPORT_MEA_TABLE_PQ_ITEM_CONF_FILE_PATH, "r") as f:
            dd = json.load(f)
        REPORT_MEA_TABLE_PQ_ITEM_CONF = [ReportDataTableItemConf(**i) for i in dd]
    except Exception:
        print(stackprinter.format())
else:
    try:
        basedir = os.path.dirname(os.path.abspath(REPORT_MEA_TABLE_PQ_ITEM_CONF_FILE_PATH))
        os.makedirs(basedir, exist_ok=True)
        with open(REPORT_MEA_TABLE_PQ_ITEM_CONF_FILE_PATH, "w", encoding="utf-8") as f:
            json.dump([ob._asdict() for ob in REPORT_MEA_TABLE_PQ_ITEM_CONF], f, ensure_ascii=False, indent=4)
    except Exception:
        print(stackprinter.format())

REPORT_MEA_TABLE_ITEM_CONFS = (
    REPORT_MEA_TABLE_I_ITEM_CONF,
    REPORT_MEA_TABLE_U_ITEM_CONF,
    REPORT_MEA_TABLE_PQ_ITEM_CONF,
)

AutoTestUpdateConf = namedtuple("AutoTestUpdateConf", "pom keyList")
# 测量输出组
AUTO_TEST_OUTPUT_MEA = (
    (
        AutoTestUpdateConf(0, ("ua_1", "ub_1", "uc_1", "ia_1", "ib_1", "ic_1")),
        KS833_OutputStatus(30, 30, 30, 0, 240, 120, 0.5, 0.5, 0.5, 0, 240, 120),
    ),
    (
        AutoTestUpdateConf(
            0, ("ua_2", "ub_2", "uc_2", "ia_2", "ib_2", "ic_2", "pa_1", "pb_1", "pc_1", "qa_1", "qb_1", "qc_1", "cos_1")
        ),
        KS833_OutputStatus(100, 100, 100, 0, 240, 120, 2.5, 2.5, 2.5, 300, 180, 60),
    ),
    (
        AutoTestUpdateConf(
            0, ("ua_3", "ub_3", "uc_3", "ia_3", "ib_3", "ic_3", "pa_2", "pb_2", "pc_2", "qa_2", "qb_2", "qc_2", "cos_2")
        ),
        KS833_OutputStatus(220, 220, 220, 0, 240, 120, 5, 5, 5, 300, 180, 60),
    ),
    (
        AutoTestUpdateConf(0, ("ua_4", "ub_4", "uc_4", "ia_4", "ib_4", "ic_4")),
        KS833_OutputStatus(250, 250, 250, 0, 240, 120, 6, 6, 6, 0, 240, 120),
    ),
)

AUTO_TEST_OUTPUT_MEA_FILE_PATH = "./config/idin201f_auto_test_output.json"
if os.path.exists(AUTO_TEST_OUTPUT_MEA_FILE_PATH) and os.path.isfile(AUTO_TEST_OUTPUT_MEA_FILE_PATH):
    try:
        with open(AUTO_TEST_OUTPUT_MEA_FILE_PATH, "r") as f:
            dd = json.load(f)
        AUTO_TEST_OUTPUT_MEA = [(AutoTestUpdateConf(**i), KS833_OutputStatus(**j)) for i, j in dd]
    except Exception:
        print(stackprinter.format())
else:
    try:
        basedir = os.path.dirname(os.path.abspath(AUTO_TEST_OUTPUT_MEA_FILE_PATH))
        os.makedirs(basedir, exist_ok=True)
        with open(AUTO_TEST_OUTPUT_MEA_FILE_PATH, "w", encoding="utf-8") as f:
            json.dump(
                [(ob._asdict(), oc._asdict()) for ob, oc in AUTO_TEST_OUTPUT_MEA], f, ensure_ascii=False, indent=4
            )
    except Exception:
        print(stackprinter.format())

# 保护输出组
AUTO_TEST_OUTPUT_PRT = (
    # U I
    (
        AutoTestUpdateConf(1, ("uab_4", "ubc_4", "uca_4", "ux_4", "ia_1", "ib_1", "ic_1", "ix_1")),
        KS833_OutputStatus(450 / ROOT_3, 450 / ROOT_3, 450 / ROOT_3, 0, 240, 120, 0.5, 0.5, 0.5, 0, 240, 120),
    ),
    (
        AutoTestUpdateConf(1, ("uab_3", "ubc_3", "uca_3", "ux_3", "ia_2", "ib_2", "ic_2", "ix_2")),
        KS833_OutputStatus(160 / ROOT_3, 160 / ROOT_3, 160 / ROOT_3, 0, 240, 120, 8, 8, 8, 0, 240, 120),
    ),
    (
        AutoTestUpdateConf(1, ("uab_2", "ubc_2", "uca_2", "ux_2", "ia_3", "ib_3", "ic_3", "ix_3")),
        KS833_OutputStatus(120 / ROOT_3, 120 / ROOT_3, 120 / ROOT_3, 0, 240, 120, 12, 12, 12, 0, 240, 120),
    ),
    (
        AutoTestUpdateConf(1, ("uab_1", "ubc_1", "uca_1", "ux_1", "ia_4", "ib_4", "ic_4", "ix_4")),
        KS833_OutputStatus(30 / ROOT_3, 30 / ROOT_3, 30 / ROOT_3, 0, 240, 120, 20, 20, 20, 0, 240, 120),
    ),
)

AUTO_TEST_OUTPUT_PRT_FILE_PATH = "./config/spac800_prt_auto_test_output.json"
if os.path.exists(AUTO_TEST_OUTPUT_PRT_FILE_PATH) and os.path.isfile(AUTO_TEST_OUTPUT_PRT_FILE_PATH):
    try:
        with open(AUTO_TEST_OUTPUT_PRT_FILE_PATH, "r") as f:
            dd = json.load(f)
        AUTO_TEST_OUTPUT_PRT = [(AutoTestUpdateConf(**i), KS833_OutputStatus(**j)) for i, j in dd]
    except Exception:
        print(stackprinter.format())
else:
    try:
        basedir = os.path.dirname(os.path.abspath(AUTO_TEST_OUTPUT_PRT_FILE_PATH))
        os.makedirs(basedir, exist_ok=True)
        with open(AUTO_TEST_OUTPUT_PRT_FILE_PATH, "w", encoding="utf-8") as f:
            json.dump(
                [(ob._asdict(), oc._asdict()) for ob, oc in AUTO_TEST_OUTPUT_PRT], f, ensure_ascii=False, indent=4
            )
    except Exception:
        print(stackprinter.format())


def getWriteAreaName(addr: int):
    """get write area name"""
    if addr == 0x0000:
        return "日期时间"
    elif addr == 0x0001:
        return "月日"
    elif addr == 0x0002:
        return "时分"
    elif addr == 0x0003:
        return "毫秒"
    elif addr == 0x0001:
        return "月日"
    elif addr in range(0x0040, 0x0043 + 1):
        return "有功电度"
    elif addr in range(0x0048, 0x004B + 1):
        return "无功电度"
    elif addr in range(0x0200, 0x0204 + 1):
        return "系统参数->保护参数"
    elif addr in range(0x0205, 0x0207 + 1):
        return "系统参数->测量参数"
    elif addr in range(0x0208, 0x0209 + 1):
        return "系统参数->显示参数"
    elif addr in range(0x0300, 0x030C + 1):
        return "开入参数->遥信去抖时间"
    elif addr in range(0x030D, 0x0319 + 1):
        return "开入参数->开入功能选择"
    elif addr in range(0x0400, 0x0409 + 1):
        return "出口参数->开出时间"
    elif addr in range(0x040A, 0x0428 + 1):
        return "出口参数->保护出口选择"
    elif addr in range(0x0600, 0x0602 + 1):
        return "通讯参数->串口1"
    elif addr in range(0x0603, 0x0605 + 1):
        return "通讯参数->串口2"
    elif addr in range(0x0606, 0x0612 + 1):
        return "通讯参数->网口1"
    elif addr in range(0x0613, 0x061F + 1):
        return "通讯参数->网口2"
    elif addr in range(0x0700, 0x0707 + 1):
        return "产品信息参数"
    elif addr in range(0x0800, 0x084B + 1):
        return "保护参数"
    elif addr == 0x0B00:
        return "遥控跳闸"
    elif addr == 0x0B01:
        return "遥控合闸"
    elif addr == 0x0B20:
        return "信号复归"
    elif addr == 0x0B21:
        return "电度清零"
    elif addr == 0x0B22:
        return "保护事件记录清零"
    elif addr == 0x0B23:
        return "遥信事件记录清零"
    elif addr == 0x0B24:
        return "故障录波记录清零"
    elif addr == 0x0E20:
        return "保护校正操作"
    elif addr == 0x0E21:
        return "恢复出厂设置"
    elif addr == 0x0E22:
        return "运行模式切换"
    elif addr in range(0x0E40, 0x0E4F + 1):
        return "低量程校正系数"
    elif addr in range(0x0E50, 0x0E5F + 1):
        return "高量程校正系数"
    elif addr in range(0x0E70, 0x0E77 + 1):
        return "开出 {} 遥控操作".format(addr - 0x0E70 + 1)
    elif addr == 0x0E90:
        return "交流旁路通道控制"
    elif addr in range(0x0E91, 0x0EA1 + 1):
        return "交流旁路值"
    else:
        return ""


PRT_AREA_NAMES = (
    "过流1段保护投退定值",
    "过流1段保护电流定值",
    "过流1段保护时间定值",
    "过流2段保护投退定值",
    "过流2段保护电流定值",
    "过流2段保护时间定值",
    "过流3段保护投退定值",
    "过流3段保护电流定值",
    "过流3段保护时间定值",
    "反时限保护投退定值",
    "反时限保护基准电流定值",
    "反时限保护时间常数定值",
    "反时限保护取曲线定值",
    "反时限保护启动倍数定值",
    "零序1段保护投退定值",
    "零序1段保护电流定值",
    "零序1段保护时间定值",
    "零序2段保护投退定值",
    "零序2段保护电流定值",
    "零序2段保护时间定值",
    "负序过流保护投退定值",
    "负序过流保护电流定值",
    "负序过流保护时间定值",
    "过负荷保护投退定值",
    "过负荷保护电流定值",
    "过负荷保护时间定值",
    "低电压保护投退定值",
    "低电压保护电压定值",
    "低电压保护时间定值",
    "过电压保护投退定值",
    "过电压保护电压定值",
    "过电压保护时间定值",
    "不平衡电流保护投退定值",
    "不平衡电流保护电流定值",
    "不平衡电流保护时间定值",
    "不平衡电压保护投退定值",
    "不平衡电压保护电压定值",
    "不平衡电压保护时间定值",
    "充电保护投退定值",
    "充电保护加速时间定值",
    "充电保护动作电流定值",
    "充电保护动作时间定值",
    "重合闸保护投退定值",
    "重合闸保护动作时间定值",
    "后加速保护投退定值",
    "后加速保护电流定值",
    "后加速保护时间定值",
    "电动机保护投退",
    "电机额定电流",
    "电机启动时间",
    "过热保护投退定值",
    "过热保护发热时间定值",
    "过热保护负序系数定值",
    "启动速断保护投退定值",
    "启动速断保护电流定值",
    "启动速断保护时间定值",
    "启动超时保护投退定值",
    "堵转保护投退定值",
    "堵转保护电流定值",
    "堵转保护时间定值",
    "重瓦斯保护投退定值",
    "重瓦斯保护时间定值",
    "轻瓦斯保护投退定值",
    "轻瓦斯保护时间定值",
    "高温段保护投退定值",
    "高温段保护时间定值",
    "超温保护投退定值",
    "超温保护时间定值",
    "压力释放保投退定值",
    "压力释放保时间定值",
    "非电量1保护投退定值",
    "非电量1保护时间定值",
    "非电量2保护投退定值",
    "非电量2保护时间定值",
    "备用",
    "备用",
)


def getPrtAreaName(addr: int):
    """get prt para addr name"""
    if addr >= 0 and addr < len(PRT_AREA_NAMES):
        return PRT_AREA_NAMES[addr]
    else:
        return "PRT_AREA_NAMES Out Range {}".format(addr)


HomeDispSelect = namedtuple("HomeDispSelect", ("offset name enable"))
HOME_DISP_ITEMS = (
    HomeDispSelect(0, "装置状态", True),
    HomeDispSelect(1, "远方/就地状态", True),
    HomeDispSelect(2, "CPU使用情况", False),
    HomeDispSelect(3, "一次/二次值选择", True),
    HomeDispSelect(4, "电机状态", True),
    HomeDispSelect(10, "Uab线电压值", True),
    HomeDispSelect(11, "Ubc线电压值", True),
    HomeDispSelect(12, "Uca线电压值", True),
    HomeDispSelect(13, "Ia相电流值", True),
    HomeDispSelect(14, "Ib相电流值", True),
    HomeDispSelect(15, "Ic相电流值", True),
    HomeDispSelect(16, "Ux不平衡电压值", True),
    HomeDispSelect(17, "Ix不平衡电流值", True),
    HomeDispSelect(18, "I1正序电流值", True),
    HomeDispSelect(19, "I2负序电流值", True),
    HomeDispSelect(20, "3I0零序电流值", True),
    HomeDispSelect(21, "R1过热热容量", True),
    HomeDispSelect(22, "R2反时限热容量", True),
    HomeDispSelect(23, "Uab线电压角度", True),
    HomeDispSelect(24, "Ubc线电压角度", True),
    HomeDispSelect(25, "Uca线电压角度", True),
    HomeDispSelect(26, "Ia相电流角度", True),
    HomeDispSelect(27, "Ib相电流角度", True),
    HomeDispSelect(28, "Ic相电流角度", True),
)
